﻿using System;
using System.IO;
using System.Linq;
using System.Windows.Media;
using System.Windows.Threading;
using System.Threading;

namespace MusicPlayer
{
    class DriverDefault : Driver
    {
        public static readonly DriverInfo DriverInformation;

        private MediaPlayer player;

        private DriverState state;

        private DispatcherTimer timer;

        public override DriverState State
        {
            get { return this.state; }
            protected set
            {
                this.state = value;

                base.StateChanged(new DriverStateArgs(this.state));

                if (this.state == DriverState.Playing)
                {
                    timer.Start();
                }
                else
                {
                    timer.Stop();
                }
            }
        }

        static DriverDefault()
        {
            DriverInformation = new DriverInfo("Default driver", "Default driver for playing media files. Version 1.0.0");
        }

        public DriverDefault()
        {
            this.timer = new DispatcherTimer();
            this.timer.Interval = new TimeSpan(0, 0, 1);
            this.timer.Tick += timer_Tick; ;
            timer.Stop();

            this.player = new MediaPlayer();

            this.player.MediaEnded += (snd, args) =>
                {
                    base.MediaEnded(new EventArgs());
                };

            this.player.MediaFailed += player_MediaFailed;

            this.State = DriverState.Stopped;
        }

        void player_MediaFailed(object sender, ExceptionEventArgs e)
        {
            //MessageBox.Show(e.ErrorException.Message);
            //throw new FormatNotSupportedException("File is either missing or it is of not supported format. " + e.ErrorException.Message, e.ErrorException);
        }

        void timer_Tick(object sender, EventArgs e)
        {
            base.TimeChanged(new DriverTimeArgs(this.player.Position));
        }

        public override void Play(string fileToPlay)
        {
            if (this.State == DriverState.Playing)
            {
                this.player.Stop();
                this.State = DriverState.Stopped;
            }

            if (this.State == DriverState.Stopped)
            {
                OpenMediaLocation(fileToPlay);

                base.MediaLocationChanged(new DriverMediaLocationArgs(fileToPlay));
            }

            this.player.Play();

            this.State = DriverState.Playing;
        }

        public override void Pause()
        {
            this.player.Pause();

            this.State = DriverState.Paused;
        }

        public override void Stop()
        {
            this.player.Stop();

            this.State = DriverState.Stopped;
        }

        public override void SetVolume(double volume)
        {
            if (volume < 0)
            {
                if (this.player.Volume - (Math.Abs(volume) / 100.0) <= 0.0)
                {
                    this.player.Volume = 0.0;
                }
                else
                {
                    this.player.Volume -= Math.Abs(volume) / 100.0;
                }
            }
            else if (volume > 100)
            {
                if (this.player.Volume + ((volume - 100) / 100.0) >= 1.0)
                {
                    this.player.Volume = 1.0;
                }
                else
                {
                    this.player.Volume += (volume - 100) / 100.0;
                }
            }
            else
            {
                this.player.Volume = volume / 100.0;
            }
        }

        public override void Mute()
        {
            this.player.IsMuted = !this.player.IsMuted;
        }

        private void OpenMediaLocation(string fileToPlay)
        {
            if (File.Exists(fileToPlay))
            {
                string mediaExtention = Path.GetExtension(fileToPlay).ToLower();
                if (mediaExtention != ".mp3" && mediaExtention != ".wav" && mediaExtention != ".wma")
                {
                    throw new DriverMediaLoadingException(
                        String.Format("Unsupported file format specified: {0}", mediaExtention));
                }
            }
            else
            {
                throw new DriverMediaLoadingException(
                    String.Format("Cannot find the file specified: {0}", fileToPlay));
            }

            this.player.Open(new Uri(fileToPlay, UriKind.Relative));

            //wait for media player to try loading the file
            Thread.Sleep(500);

            if (this.player.HasAudio == false)
            {
                throw new DriverMediaLoadingException(
                    String.Format("Unable to load file: {0}", fileToPlay));
            }
        }
    }
}
